package org.libarae.communication;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.xml.parsers.ParserConfigurationException;

import org.libarae.communication.common.Type;
import org.libarae.communication.request.Request;
import org.libarae.communication.response.LoginResponse;
import org.libarae.communication.response.NewUserResponse;
import org.libarae.communication.response.Response;
import org.xml.sax.SAXException;

public class ClientInterface {
	//used to indicate the end of the message
	public static final String END_RESPONSE_STRING = "TERMINATE~!@#~"+(char)4;
	private static String mServerAddress = null;
	private static int mPortNumber = 80;	//default port 80
	private static String mAccessKey = ""; 	//sent back from server

	public ClientInterface(String serverAddress) throws UnknownHostException{
		//set this server address we are givin
		setServerAddress(serverAddress);
	}
	
	public static Response sendRequest(Request request) throws IOException, XmlParseException, NotLogedInException, NoServerAddressException, SAXException, ParserConfigurationException{
		//make sure we are logged in and we have a good server address
		if(mAccessKey == null || mAccessKey.equals("")){
			if(request.getType() != Type.LOGIN && request.getType() != Type.NEW_USER && request.getType() != Type.SERVER_PING)
				throw new NotLogedInException("Not Logged in");
		}
		
		//check to make sure we have a server address
		if(mServerAddress == null || mServerAddress.equals(""))
			throw new NoServerAddressException("Server Address not set");
		
		//set the access key
		request.setAccessKey(mAccessKey);		
		
		//get the xml from the object
		String sendXml = RequestXmlHandler.createXML(request);
		
		//open the socket and set timeout
		Socket socket = new Socket(mServerAddress, mPortNumber);
		//set the time out of 60s
		socket.setSoTimeout(90000); 
		
		//send the xml to the server
		PrintWriter pWriter = new PrintWriter(socket.getOutputStream());
		pWriter.println(sendXml);
		pWriter.println(END_RESPONSE_STRING);
		pWriter.flush();
		
		//get object back
		BufferedReader buffRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		StringBuilder strBuild = new StringBuilder();
		String temp;
		while((temp = buffRead.readLine()) != null)
			strBuild.append(temp);
		
		//close all of the streams
		buffRead.close();
		pWriter.close();
		socket.close();
		
		//get the xml string
		String responseXml = strBuild.toString();
		
		//convert the xml into the Response object
		Response res = ResponseXmlHandler.parseXML(responseXml);
				
		//check to see if we need to grab the access key, if so get it
		if(res.getType() == Type.LOGIN && res.getStatus() == Response.STATUS_GOOD){
			LoginResponse logRes = (LoginResponse)res;
			mAccessKey = logRes.getAcessKey();
			logRes.setAcessKey("");
		}
		else if(res.getType() == Type.NEW_USER && res.getStatus() == Response.STATUS_GOOD){
			NewUserResponse newRes = (NewUserResponse)res;
			mAccessKey = newRes.getAcessKey();
			newRes.setAcessKey("");
		}
		else if(res.getType() == Type.LOGOUT){
			mAccessKey = "";
		}
		
		//return the object
		return res;
	}
	
	//gets the server address 
	public static String getServerAddress() {
		return mServerAddress;
	}

	//get the server port
	public static int getPortNumber() {
		return mPortNumber;
	}

	//sets the server address into the proper fields
	public static void setServerAddress(String serverAddress) {
		//format the address correctly
		String[] add = serverAddress.split(":");
		
		if(add.length <= 1){
			//we only have the host name
			mServerAddress = serverAddress;
			mPortNumber = 80;
		}
		else{
			mServerAddress = add[0];
			mPortNumber = Integer.parseInt(add[1]);
		}	
	}
}